"""
导出服务模块
提供数据导出的核心业务逻辑
"""

import csv
import io
import tempfile
from datetime import datetime
from typing import List, Dict, Any, Optional

from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, text, desc

from db.models.scan import ScanTask, ScanResult, AIAnalysisResult
from core.utils.time_utils import parse_datetime, parse_time_range


class ExportService:
    """导出服务类"""
    
    def __init__(self, db: AsyncSession):
        self.db = db
    
    async def export_scan_data(self, task_id: int, format_type: str = "csv") -> Dict[str, Any]:
        """
        导出扫描数据
        
        Args:
            task_id: 任务ID
            format_type: 导出格式 (csv/excel)
            
        Returns:
            包含导出数据的响应字典
        """
        try:
            # 获取任务信息
            task = await self.db.get(ScanTask, task_id)
            if not task:
                raise ValueError("任务不存在")
            
            # 获取所有扫描结果
            results = await self.db.execute(
                select(ScanResult).where(ScanResult.task_id == task_id)
            )
            results = results.scalars().all()
            
            if not results:
                raise ValueError("没有找到扫描结果")
            
            # 准备导出数据
            export_data = []
            for result in results:
                data_row = {
                    "任务ID": result.task_id,
                    "文件路径": result.file_path,
                    "函数名": result.function_name,
                    "开始行": result.start_line,
                    "结束行": result.end_line,
                    "问题类型": result.issue_type,
                    "严重程度": result.severity,
                    "问题描述": result.message,
                    "修复建议": result.suggestion,
                    "创建时间": result.created_at.strftime("%Y-%m-%d %H:%M:%S") if result.created_at else ""
                }
                export_data.append(data_row)
            
            # 根据格式生成文件
            if format_type.lower() == "csv":
                file_content, filename = await self._generate_csv(export_data, task)
            elif format_type.lower() == "excel":
                file_content, filename = await self._generate_excel(export_data, task)
            else:
                raise ValueError("不支持的导出格式")
            
            return {
                "filename": filename,
                "content": file_content,
                "format": format_type,
                "total_records": len(export_data)
            }
            
        except Exception as e:
            print(f"导出扫描数据时发生错误: {str(e)}")
            raise
    
    async def export_all_data(self, filters: Dict[str, Any], format_type: str = "csv") -> Dict[str, Any]:
        """
        导出所有扫描数据
        
        Args:
            filters: 筛选条件
            format_type: 导出格式 (csv/excel)
            
        Returns:
            包含导出数据的响应字典
        """
        try:
            # 构建基础查询
            base_query = select(ScanTask, ScanResult).join(
                ScanResult, ScanTask.id == ScanResult.task_id
            )
            
            # 添加筛选条件
            if filters.get('repo_url'):
                base_query = base_query.where(ScanTask.repo_url.like(f"%{filters['repo_url']}%"))
            
            if filters.get('branch'):
                base_query = base_query.where(ScanTask.branch.like(f"%{filters['branch']}%"))
            
            if filters.get('scan_type'):
                base_query = base_query.where(ScanTask.scan_type == filters['scan_type'])
            
            if filters.get('status'):
                base_query = base_query.where(ScanTask.status == filters['status'])
            
            # 处理时间筛选条件
            base_query = await self._apply_time_filters(base_query, filters)
            
            # 执行查询
            result = await self.db.execute(base_query)
            rows = result.all()
            
            if not rows:
                raise ValueError("没有找到符合条件的数据")
            
            # 准备导出数据
            export_data = []
            for task, scan_result in rows:
                data_row = {
                    "任务ID": task.id,
                    "仓库地址": task.repo_url,
                    "分支": task.branch,
                    "扫描类型": task.scan_type,
                    "任务状态": task.status,
                    "文件路径": scan_result.file_path,
                    "函数名": scan_result.function_name,
                    "开始行": scan_result.start_line,
                    "结束行": scan_result.end_line,
                    "问题类型": scan_result.issue_type,
                    "严重程度": scan_result.severity,
                    "问题描述": scan_result.message,
                    "修复建议": scan_result.suggestion,
                    "任务创建时间": task.created_at.strftime("%Y-%m-%d %H:%M:%S") if task.created_at else "",
                    "结果创建时间": scan_result.created_at.strftime("%Y-%m-%d %H:%M:%S") if scan_result.created_at else ""
                }
                export_data.append(data_row)
            
            # 根据格式生成文件
            if format_type.lower() == "csv":
                file_content, filename = await self._generate_csv_all(export_data, filters)
            elif format_type.lower() == "excel":
                file_content, filename = await self._generate_excel_all(export_data, filters)
            else:
                raise ValueError("不支持的导出格式")
            
            return {
                "filename": filename,
                "content": file_content,
                "format": format_type,
                "total_records": len(export_data)
            }
            
        except Exception as e:
            print(f"导出所有数据时发生错误: {str(e)}")
            raise
    
    async def _generate_csv(self, data: List[Dict[str, Any]], task: ScanTask) -> tuple:
        """
        生成CSV文件
        
        Args:
            data: 导出数据
            task: 任务对象
            
        Returns:
            (文件内容, 文件名)
        """
        output = io.StringIO()
        writer = csv.DictWriter(output, fieldnames=data[0].keys())
        writer.writeheader()
        writer.writerows(data)
        
        filename = f"scan_results_task_{task.id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
        return output.getvalue(), filename
    
    async def _generate_csv_all(self, data: List[Dict[str, Any]], filters: Dict[str, Any]) -> tuple:
        """
        生成所有数据的CSV文件
        
        Args:
            data: 导出数据
            filters: 筛选条件
            
        Returns:
            (文件内容, 文件名)
        """
        output = io.StringIO()
        writer = csv.DictWriter(output, fieldnames=data[0].keys())
        writer.writeheader()
        writer.writerows(data)
        
        filename = f"all_scan_results_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
        return output.getvalue(), filename
    
    async def _generate_excel(self, data: List[Dict[str, Any]], task: ScanTask) -> tuple:
        """
        生成Excel文件
        
        Args:
            data: 导出数据
            task: 任务对象
            
        Returns:
            (文件内容, 文件名)
        """
        try:
            import pandas as pd
            
            df = pd.DataFrame(data)
            output = io.BytesIO()
            df.to_excel(output, index=False, engine='openpyxl')
            output.seek(0)
            
            filename = f"scan_results_task_{task.id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
            return output.getvalue(), filename
            
        except ImportError:
            raise ValueError("Excel导出需要安装pandas和openpyxl库")
    
    async def _generate_excel_all(self, data: List[Dict[str, Any]], filters: Dict[str, Any]) -> tuple:
        """
        生成所有数据的Excel文件
        
        Args:
            data: 导出数据
            filters: 筛选条件
            
        Returns:
            (文件内容, 文件名)
        """
        try:
            import pandas as pd
            
            df = pd.DataFrame(data)
            output = io.BytesIO()
            df.to_excel(output, index=False, engine='openpyxl')
            output.seek(0)
            
            filename = f"all_scan_results_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
            return output.getvalue(), filename
            
        except ImportError:
            raise ValueError("Excel导出需要安装pandas和openpyxl库")
    
    async def _apply_time_filters(self, base_query, filters: Dict[str, Any]):
        """
        应用时间筛选条件
        
        Args:
            base_query: 基础查询
            filters: 筛选条件
            
        Returns:
            应用了时间筛选的查询
        """
        # 处理 start_time 和 end_time
        if filters.get('start_time') or filters.get('end_time'):
            if filters.get('start_time'):
                start_dt = parse_datetime(filters['start_time'])
                base_query = base_query.where(ScanTask.created_at >= start_dt)
            
            if filters.get('end_time'):
                end_dt = parse_datetime(filters['end_time'])
                base_query = base_query.where(ScanTask.created_at <= end_dt)
        
        # 处理 created_at_start 和 created_at_end
        elif filters.get('created_at_start') or filters.get('created_at_end'):
            if filters.get('created_at_start'):
                created_start_dt = parse_datetime(filters['created_at_start'])
                base_query = base_query.where(ScanTask.created_at >= created_start_dt)
            
            if filters.get('created_at_end'):
                created_end_dt = parse_datetime(filters['created_at_end'])
                base_query = base_query.where(ScanTask.created_at <= created_end_dt)
        
        # 处理 updated_at_start 和 updated_at_end
        if filters.get('updated_at_start') or filters.get('updated_at_end'):
            if filters.get('updated_at_start'):
                updated_start_dt = parse_datetime(filters['updated_at_start'])
                base_query = base_query.where(ScanTask.updated_at >= updated_start_dt)
            
            if filters.get('updated_at_end'):
                updated_end_dt = parse_datetime(filters['updated_at_end'])
                base_query = base_query.where(ScanTask.updated_at <= updated_end_dt)
        
        # 处理时间范围参数
        if filters.get('created_at_range'):
            start_time_str, end_time_str = parse_time_range(filters['created_at_range'])
            if start_time_str:
                created_start_dt = parse_datetime(start_time_str)
                base_query = base_query.where(ScanTask.created_at >= created_start_dt)
            if end_time_str:
                created_end_dt = parse_datetime(end_time_str)
                base_query = base_query.where(ScanTask.created_at <= created_end_dt)
        
        if filters.get('updated_at_range'):
            start_time_str, end_time_str = parse_time_range(filters['updated_at_range'])
            if start_time_str:
                updated_start_dt = parse_datetime(start_time_str)
                base_query = base_query.where(ScanTask.updated_at >= updated_start_dt)
            if end_time_str:
                updated_end_dt = parse_datetime(end_time_str)
                base_query = base_query.where(ScanTask.updated_at <= updated_end_dt)
        
        return base_query 